<script setup>
import spark from "spark-md5"

const sparkMd5 = new spark()
import {ElMessage, ElMessageBox} from "element-plus"
import {reactive, ref, onMounted, nextTick} from "vue";
import VideoApi from "../../api/VideoApi.js";
import {Search} from "@element-plus/icons-vue";
import VideoCategoryApi from "../../api/VideoCategoryApi.js";
import videoTagApi from "@/api/VideoTagApi.js";

const categoryTreeProps = reactive({
  value: "categoryId",
  label: "categoryName",
  children: "children",
  emitPath: false
})
const state = reactive({
  totalNum: 0,
  videoList: [],
  queryDto: {
    videoCode: null,
    videoName: null,
    pageNum: 1,
    size: 5
  },
  drawer: false,
  dialog: {
    saveOrUpdateDialog: false,
    uploadVideoDialog: false,
    uploadProgressDialog: false
  },
  isAddOperation: true,
  videoInfo: {
    videoId: null,
    videoCode: null,
    videoName: null,
    categoryId: null,
    director: null,
    actor: null,
    releaseTime: null,
    isMultiple: null,
    seq: null,
    area: null,
    language: null
  },
  categoryTree: [],
  uploadProgress: 0,
  tagList:[],
  currentUploadVideoCode :null,
  isExist:false
})
const getVideoList = () => {
  VideoApi.pageQueryVideoList(state.queryDto).then(res => {
    state.videoList = res.data.data
    state.totalNum = res.data.total
  })
}
const currentPageChange = (page) => {
  state.queryDto.pageNum = page
  getVideoList()
}

onMounted(() => {
  getVideoList()
})

const openAddOrUpdateDialog = (isAdd, videoCode, rootVideo) => {
  state.isAddOperation = isAdd
  state.drawer = true
  VideoCategoryApi.getVideoCategoryTree().then(res => {
    state.categoryTree = res.data
    videoTagApi.getAllTags().then(res=>{
      state.tagList = res.data
      if (isAdd) {
        state.videoInfo = {
          videoId: null,
          videoCode: null,
          videoName: null,
          categoryId: null,
          director: null,
          actor: null,
          releaseTime: null,
          isMultiple: null,
          seq: null,
          rootId: -1
        }
        if (rootVideo) {
          state.videoInfo.categoryId = rootVideo.category.categoryId
          state.videoInfo.rootId = rootVideo.videoId
          state.videoInfo.director = rootVideo.actor.join(";")
          state.videoInfo.videoName = rootVideo.videoName
          state.videoInfo.releaseTime = rootVideo.releaseTime
          state.videoInfo.actor = rootVideo.actor.join(";")
        }

      } else {
        VideoApi.getVideoInfo(videoCode).then(res => {
          state.videoInfo = res.data
          if (res.data.actor && res.data.actor.length > 0) {
            state.videoInfo.actor = res.data.actor.join(";")
          }
          if (res.data.director && res.data.director.length > 0) {
            state.videoInfo.director = res.data.director.join(";")
          }
          state.videoInfo.categoryId = res.data.category.categoryId
        })
      }
    })

  })
}
const videoFormRef = ref()
const saveOrUpdateSubmit = () => {
  videoFormRef.value.validate((valid, fields) => {

    if (valid) {
      const operation = state.isAddOperation ? VideoApi.publishVideo : VideoApi.updateVideo
      if (state.videoInfo.isMultiple) {
        if (state.videoInfo.seq === null || state.videoInfo.seq === "") {
          ElMessage.error("请填写当前集数!")
          return
        }
      } else {
        state.videoInfo.seq = null
      }
      state.videoInfo.isMultiple = state.videoInfo.isMultiple ? 1 : 0
      operation(state.videoInfo).then(res => {
        if (!res.flag) {
          ElMessage.error(res.message)
          return
        }
        ElMessage.success(res.message)
        state.drawer = false
        getVideoList()
      })
    }
  })
}

const openUplaodVideoDailog = (videoCode) => {
  state.dialog.uploadVideoDialog = true

  state.currentUploadVideoCode = videoCode
}

const closeUploadDialog = ()=>{
  state.dialog.uploadVideoDialog = false
  state.dialog.uploadProgressDialog = false
  state.currentUploadVideoCode = null
  state.uploadProgress = 0
  getVideoList()
}
//上传视频
const uploadVideo = async (file) => {
  state.dialog.uploadProgressDialog = true
  // 文件先分片
  const fileChunks = createChunks(file.raw, 25 * 1024 * 1024);
  // 计算MD5
  const fileMd5 = await computeFileMD5(fileChunks);
  const recursiveUpload = async (i) => {
    if (i <= fileChunks.length) {
      let fileName = file.raw.name
      const formdata = new FormData();

      formdata.append("videoCode",state.currentUploadVideoCode)
      formdata.append('md5', fileMd5);
      formdata.append('totalSlices', fileChunks.length);
      formdata.append('seq', i);
      formdata.append("file", fileChunks[i - 1], fileMd5 + "_" + i + fileName.substring(fileName.lastIndexOf('.')));
      try {
        const res = await httpUploadFile(formdata);
        console.log('***1')
        if (res.data && res.data!==''){
          console.log('***2')
          console.log("上传结果")
          console.log(res)
          closeUploadDialog()
          return
        }
        console.log('***3')
        if (i === fileChunks.length) {
          state.uploadProgress = 100
          VideoApi.mergeVideoFile({fileName: fileName, md5: fileMd5,videoCode:state.currentUploadVideoCode}).then(res => {
            closeUploadDialog()

          })
        }
      } catch (error) {
        ElMessage.error(error)
      }
      state.uploadProgress = Math.floor((i / fileChunks.length) * 100)
      await recursiveUpload(i + 1);
    }
  }

  await recursiveUpload(1);
}

const httpUploadFile = async (formData) => {
  return VideoApi.uploadVideo(formData);
}
const computeFileMD5 = (fileChunks) => {
  return new Promise(resolve => {
    function _read(i) {
      if (i >= fileChunks.length) {
        resolve(sparkMd5.end())
        return;
      }
      const blob = fileChunks[i]
      const reader = new FileReader()
      reader.onload = e => {
        const bytes = e.target.result; //读取到的字节数组
        sparkMd5.append(bytes)
        _read(i + 1)
      }
      reader.readAsArrayBuffer(blob)
    }

    _read(0)
  })

}
const createChunks = (file, chunkSize) => {
  const result = []
  for (let i = 0; i < file.size; i += chunkSize) {
    result.push(file.slice(i, i + chunkSize))
  }
  return result
}

const videoFormRule = reactive({
  videoName: [{required: true, message: "请填写视频名称!", trigger: 'blue'}],
  director: [{required: true, message: "请填写影片导演!", trigger: 'blue'}],
  actor: [{required: true, message: "请填写影片主演!", trigger: 'blue'}],
  releaseTime: [{required: true, message: "请填写影片上映名称!", trigger: 'blue'}],
  area: [{required: true, message: "请填写影片上映地区!", trigger: 'blue'}],
  language: [{required: true, message: "请填写影片语言!", trigger: 'blue'}],
  isMultiple: [{required: true, message: "请选择该影片是否多级!", trigger: 'blue', type: Boolean}],
  categoryId: [{required: true, message: "请选择影片分类!", trigger: 'blue'}],
  videoDesc: [{required: true, message: "请输入影片描述!", trigger: 'blue'}]
})
</script>
<template>
  <el-card style="--el-card-border-radius: 8px;--el-card-padding: 10px">
    <el-form :inline="true">
      <el-form-item>
        <el-input v-model="state.queryDto.videoCode" placeholder="视频编码" clearable/>
      </el-form-item>
      <el-form-item>
        <el-input v-model="state.queryDto.videoName" placeholder="视频名称" clearable/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" :icon="Search" @click="getVideoList">搜索</el-button>
      </el-form-item>
    </el-form>

  </el-card>
  <p style="margin: 5px 0">
    <el-button type="success" @click="openAddOrUpdateDialog(true)">
      添加影片
      <el-icon class="el-icon--right">
        <Plus/>
      </el-icon>
    </el-button>
  </p>
  <el-table :data="state.videoList" border style="width: 100%" :tree-props="{ children: 'children' }"
            row-key="videoCode">
    <el-table-column align="center" prop="videoCode" label="影片编码" width="180"/>
    <el-table-column align="center" prop="videoName" label="影片名称"/>
    <el-table-column align="center" label="影片分类">
      <template #default="scope">
        <span v-if="scope.row.parentCategory">{{ scope.row.parentCategory.categoryName }}/</span>
        <span v-if="scope.row.category">{{ scope.row.category.categoryName }}</span>
      </template>
    </el-table-column>
    <el-table-column align="center" label="导演">
      <template #default="scope">
        <el-tag style="margin-right: 5px" v-for="(d,index) in scope.row.director" :key="index">{{ d }}</el-tag>
      </template>
    </el-table-column>
    <el-table-column align="center" label="主演">
      <template #default="scope">
        <el-tag style="margin-right: 5px" v-for="(a,index) in scope.row.actor" :key="index">{{
            a
          }}
        </el-tag>
      </template>
    </el-table-column>
    <el-table-column align="center" prop="releaseTime" label="上映时间"/>
    <el-table-column align="center" label="评分">
      <template #default="scope">
        <div style="display: flex;flex-direction: column;justify-content: center">
          <span style="font-weight: 600;color: #ff4949">{{ scope.row.rate }}&nbsp;分</span>
          <el-rate size="small" v-model="scope.row.rate" :max="10" disabled/>
        </div>
      </template>
    </el-table-column>
    <el-table-column align="center" prop="videoDesc" label="简介" show-overflow-tooltip/>
    <el-table-column align="center" prop="isMultiple" label="是否多集">
      <template #default="scope">
        <el-tag :type="scope.row.isMultiple?'success':'primary'">{{ scope.row.isMultiple ? '是' : '否' }}</el-tag>
      </template>
    </el-table-column>
    <el-table-column align="center" prop="seq" label="序列号"/>
    <el-table-column align="center" label="操作" width="250px">
      <template #default="scope">
        <el-button type="primary" text :disabled="!scope.row.isMultiple && scope.row.rootId ===-1" icon="DocumentAdd"
                   @click="openAddOrUpdateDialog(true,null,scope.row)"/>
        <el-button type="primary" text icon="VideoCamera" @click="openUplaodVideoDailog(scope.row.videoCode)"/>
        <el-button type="primary" text icon="Edit" @click="openAddOrUpdateDialog(false,scope.row.videoCode)"/>
        <el-popconfirm :title="`确定删除视频【${scope.row.videoName}】吗？`"
                       @confirm=""
                       confirm-button-text="确认" confirm-button-type="danger" cancel-button-text="取消">
          <template #reference>
            <el-button type="danger" text icon="Delete"/>
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
  </el-table>
  <el-pagination
      style="margin:20px auto;justify-content: center"
      small
      background
      :total="state.totalNum"
      :default-page-size="state.queryDto.size"
      layout="prev, pager, next"
      :current-page="state.queryDto.pageNum"
      @update:current-page="currentPageChange"
  />
  <el-drawer
      v-model="state.drawer"
      :title="state.isAdd?'添加影片':'修改影片'"
      :direction="direction"
      :before-close="handleClose"
      size="40%"
  >

    <el-form :model="state.videoInfo" label-width="120px" ref="videoFormRef" :rules="videoFormRule">
      <el-form-item label="影片名称" prop="videoName">
        <el-input v-model="state.videoInfo.videoName"/>
      </el-form-item>
      <el-form-item label="导演" prop="director">
        <el-input v-model="state.videoInfo.director"/>
      </el-form-item>
      <el-form-item label="主演" prop="actor">
        <el-input v-model="state.videoInfo.actor"/>
      </el-form-item>
      <el-form-item label="上映时间" prop="releaseTime">
        <el-input v-model="state.videoInfo.releaseTime"/>
      </el-form-item>
      <el-form-item label="地区" prop="area">
        <el-input v-model="state.videoInfo.area"/>
      </el-form-item>
      <el-form-item label="语言" prop="language">
        <el-input v-model="state.videoInfo.language"/>
      </el-form-item>
      <el-form-item label="是否多集" prop="isMultiple">
        <el-select v-model="state.videoInfo.isMultiple" placeholder="请选择是否多集">
          <el-option label="是" :value="true"></el-option>
          <el-option label="否" :value="false"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="当前集数" v-if="state.videoInfo.isMultiple">
        <el-input-number v-model="state.videoInfo.seq" :min="1" style="width: 100%"/>
      </el-form-item>
      <el-form-item label="影片分类" prop="categoryId">
        <el-cascader style="width:100%" :disabled="state.videoInfo.rootId &&state.videoInfo.rootId!==-1"
                     v-model="state.videoInfo.categoryId" placeholder="请选择影片分类" :props="categoryTreeProps"
                     :options="state.categoryTree"/>
      </el-form-item>
      <el-form-item label="影片简介" prop="videoDesc">
        <el-input type="textarea" v-model="state.videoInfo.videoDesc"/>
      </el-form-item>
      <el-form-item label="视频标签" prop="tagList">
        <el-select
            style="width:100%"
            v-model="state.videoInfo.tagList"
            multiple
            placeholder="请添加视频标签"

        >
          <el-option
              v-for="item in state.tagList"
              :key="item.tagId"
              :label="item.tagName"
              :value="item.tagName"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button @click="state.drawer = false">取消</el-button>
        <el-button type="primary" @click="saveOrUpdateSubmit">
          保存
        </el-button>
      </el-form-item>
    </el-form>

  </el-drawer>

  <!--视频上传对话框-->
  <el-dialog style="border-radius: 12px" v-model="state.dialog.uploadVideoDialog" title="上传视频资源" width="50%"
             @closed="closeUploadDialog"
             center :close-on-click-modal="false">
    <el-upload
        class="upload-demo"
        :auto-upload="false"
        drag
        action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
        accept='.mp4,.mkv'
        :on-change="uploadVideo"
    >
      <el-icon class="el-icon--upload">
        <upload-filled/>
      </el-icon>
      <div class="el-upload__text">
        拖拽视频文件上传 或者 <em>点击上传</em>
      </div>
      <template #tip>
        <div class="el-upload__tip">
          <!--          jpg/png files with a size less than 500kb-->
        </div>
      </template>
    </el-upload>
  </el-dialog>
  <!-- 上传进度对话框 -->
  <el-dialog v-model="state.dialog.uploadProgressDialog" title="文件上传中"
             style="border-radius: 12px;display: flex;align-items: center;flex-direction: column;"

             width="35%" center :close-on-click-modal="false">
    <el-progress type="circle" style="text-align: center"  :percentage="state.uploadProgress" striped-flow>
      <template #default="{ percentage }">
        <span class="percentage-value">{{ percentage }}%</span>
        <span class="percentage-label">文件上传中</span>
      </template>
    </el-progress>
  </el-dialog>
</template>
<style scoped lang="less">
:deep(.el-dialog--center .el-dialog__body){
  text-align: center!important;
}
.percentage-value {
  display: block;
  margin-top: 10px;
  font-size: 28px;
}

.percentage-label {
  display: block;
  margin-top: 10px;
  font-size: 12px;
}
</style>


